// TGF Skim - Ported by MIDIMan

freeslot(
	"MT_TGFSKIM",
	"S_TGFSKIM_WAIT",
	"S_TGFSKIM_WARMUP",
	"S_TGFSKIM_DROP",
	"SPR_TSKM"
)

local function A_TGFDropMine(actor, var1, var2)
	if not (actor and actor.valid) then return end
	
	local mine = P_SpawnMobjFromMobj(actor, 0, 0, -actor.info.height/2, actor.info.raisestate)
	mine.target = actor // So the TGF Bomber doesn't die from its own mine
	P_SetObjectMomZ(mine, -8*FRACUNIT)
	
	S_StartSound(actor, actor.info.attacksound)
end

local function TGFCheckInWater(mo, sector)
	if not (mo and mo.valid
	and sector and sector.valid)
		return
	end
	
	local inWater = false
	local highestRover = nil
	local verticalFlip = (mo.eflags & MFE_VERTICALFLIP) or (mo.flags2 & MF2_OBJECTFLIP)
	
	for rover in sector.ffloors()
		if rover and rover.valid 
		and (rover.flags & FF_EXISTS) 
		and (rover.flags & FF_SWIMMABLE)
			if highestRover and highestRover.valid
			and (not verticalFlip and rover.topheight < highestRover.topheight)
			//or (verticalFlip and rover.bottomheight > highestRover.bottomheight))
				continue
			end
			
			if P_InsideANonSolidFFloor(mo, rover)
			or (not verticalFlip and mo.z >= rover.topheight)
			//or (verticalFlip and mo.z + mo.height <= rover.bottomheight)
				mo.watertop = rover.topheight
				mo.waterbottom = rover.bottomheight
				inWater = true
			end
			
			highestRover = rover
		end
	end
	
	return {inWater, mo.watertop, mo.waterbottom}
end

addHook("MobjThinker", function(mo)
	if not (mo and mo.valid) then return end
	if mo.health <= 0 then return end
	
	local speed = FixedMul(mo.info.speed, mo.scale)
	local targetDist = 0
	local targetAngle = mo.angle
	
	local offset = {x = 0, y = 0}
	
	P_SupermanLook4Players(mo)
	if mo.target and mo.target.valid
		targetDist = FixedHypot(mo.target.x - mo.x, mo.target.y - mo.y)
		if targetDist < speed then speed = targetDist end
		targetAngle = R_PointToAngle2(mo.x, mo.y, mo.target.x, mo.target.y)
		
		offset.x = FixedMul(cos(targetAngle), speed)
		offset.y = FixedMul(sin(targetAngle), speed)
	end
	
	local inWater = false
	local stillInWater = false
	
	// This currently doesn't have support for slopes, 
	// but it doesn't need it for SRB2TP
	local inWaterResult = TGFCheckInWater(mo, R_PointInSubsector(mo.x, mo.y).sector)
	local stillInWaterResult = TGFCheckInWater(mo, R_PointInSubsector(mo.x + offset.x, mo.y + offset.y).sector)
	
	mo.watertop = inWaterResult[2]
	mo.waterbottom = inWaterResult[3]
	
	inWater = inWaterResult[1]
	stillInWater = stillInWaterResult[1]
	
	// Attempt to redefine mo.floorz and mo.ceilingz
	if mo.watertop <= mo.floorz 
		mo.watertop = mo.floorz
	end
	if mo.waterbottom <= mo.ceilingz
		mo.waterbottom = mo.ceilingz
	end
	
	// Make the skim follow the z-position of the lowest possible floor or watertop
	if inWater
		if mo.target and mo.target.valid and stillInWater
			//P_TryMove(mo, mo.x + offset.x, mo.y + offset.y, false)
			P_InstaThrust(mo, targetAngle, speed)
		else
			mo.momx = 0
			mo.momy = 0
		end
		if verticalFlip then mo.z = mo.waterbottom - mo.height
		else mo.z = mo.watertop end
	else
		if verticalFlip then mo.z = mo.ceilingz - mo.height
		else mo.z = mo.floorz end
		mo.momx = 0
		mo.momy = 0
		mo.momz = 0
	end
end, MT_TGFSKIM)

mobjinfo[MT_TGFSKIM] = {
	//$Name "TGF Skim"
	//$Sprite TSKMA0
	//$Category TGF/Concept Enemies
	doomednum = 162,
	spawnstate = S_TGFSKIM_WAIT,
	spawnhealth = 1,
	attacksound = sfx_s3k51,
	deathstate = S_XPLD_FLICKY,
	deathsound = sfx_pop,
	speed = 2*FRACUNIT,
	radius = 20*FRACUNIT,
	height = 32*FRACUNIT,
	damage = 1,
	raisestate = MT_RETROBOBMMINE,
	flags = MF_ENEMY|MF_SLIDEME|MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY
}

states[S_TGFSKIM_WAIT] =	{SPR_TSKM,	A,							105,	nil,			0,	0,	S_TGFSKIM_WARMUP}
states[S_TGFSKIM_WARMUP] =	{SPR_TSKM,	A|FF_ANIMATE|FF_FULLBRIGHT,	24,		nil,			12,	2,	S_TGFSKIM_DROP}
states[S_TGFSKIM_DROP] =	{SPR_TSKM,	A,							0,		A_TGFDropMine,	0,	0,	S_TGFSKIM_WAIT}


//Puyo
if not(kirbyabilitytable)
    rawset(_G, "kirbyabilitytable", {})
end
kirbyabilitytable[MT_TGFSKIM] = 4    // Makes MT_TGFSKIM give BOMB
